<?php

namespace app\job;

use app\common\enum\DrawEnum;
use app\common\model\draw\DrawTask;
use app\common\service\discord\DiscordSubmitService;
use think\facade\Log;
use think\queue\Job;
use WpOrg\Requests\Requests;

class DrawJob
{
    public function fire(Job $job, array $data)
    {
        $attemptsNums = $job->attempts();
        echo "\n\n";
        echo "执行的任务: RT:$attemptsNums@taskId:" . $data['task_id'] . "\n";

        // 更新任务状态
        $taskModel = new DrawTask();
        $task = $taskModel->findOrEmpty($data['id']);
        if ($task->isEmpty()) {
            echo "任务不存在: " . $data['task_id'] . " \n";
            $job->delete();
            return;
        }

        // 非待处理状态
        if ($task->status != DrawEnum::STATUS_NOT_START) {
            echo "任务非待处理状态: " . $data['task_id'] . " \n";
            $job->delete();
            return;
        }

        // 重试多次且超过记录创建时间15分钟即标记为失败
        if ($job->attempts() > 3 && time() > strtotime($task->create_time) + 900) {
            // 更新绘画记录
            $task->fail_reason = "任务已重试多次且超过15分钟，标记失败";
            $task->status = DrawEnum::STATUS_FAIL;
            $task->save();

            // 删除任务
            echo "任务已重试多次且超过15分钟，标记失败: " . $data['task_id'] . " \n";
            $job->delete();

            // 通知回调地址
            $this->notifyFail($task, "服务繁忙,请重试");
            return;
        }

        // 查询执行中的数量
        $taskRunning = $taskModel->where('token', $task->token)
            ->whereIn('status', [
                DrawEnum::STATUS_SUBMIT,
                DrawEnum::STATUS_IN_PROGRESS
            ])->count();

        if ($taskRunning > 10) {
            echo "等待或运行中数量:" . $taskRunning . ",延迟10秒" . " \n";;
            $job->release(10);
            return;
        }

        $task->status = DrawEnum::STATUS_SUBMIT;
        $task->submit_time = time();
        $task->save();

        try {
            // 提交请求到discord
            $discordSubmit = new DiscordSubmitService($task->token);

            switch ($task['action']) {
                case DrawEnum::ACTION_GENERATE:
                    $discordSubmit->imagine($task->prompt_desc);
                    break;
                case DrawEnum::ACTION_UPSAMPLE:
                    $discordSubmit->upscale($task->image_msg_id, $task->index, $task->image_msg_hash);
                    break;
                case DrawEnum::ACTION_VARIATION:
                    $discordSubmit->variate($task->image_msg_id, $task->index, $task->image_msg_hash);
                    break;
            }

        } catch (\Exception $e) {
            $errMsg = "任务提交失败: " . $task['task_id'] . ':__@__:' . $e->getMessage();
            Log::error($errMsg);
            echo $errMsg . "\n";

            // 更新任务信息
            $task->fail_reason = $e->getMessage();
            $task->status = DrawEnum::STATUS_FAIL;
            $task->save();

            // 提交失败通知
            $this->notifyFail($task, $e->getMessage());

        } finally {
            // 删除任务
            $job->delete();
        }
    }

    private function notifyFail(DrawTask $task, $failMsg)
    {
        try {
            // 通知回调地址提交任务失败
            if (!empty($task->notify_hook)) {
                $notifyData = [
                    'code' => 0,
                    'msg' => $failMsg,
                    'data' => [
                        'task_id' => $task['task_id'] ?? '',
                    ],
                ];
                $headers = [
                    "Content-Type" => "application/json;charset=UTF-8",
                ];
                Requests::post($task->notify_hook, $headers, json_encode($notifyData, JSON_UNESCAPED_UNICODE));
            }
        } catch (\Exception $e) {
            $errMsg = "任务通知失败: " . $task['task_id'] . ':__@__:' . $e->getMessage();
            Log::error($errMsg);
            echo $errMsg . "\n";
        }
    }

}